import java.io.Serializable;

abstract public class Instruccion implements Serializable {
	public enum ICOD {
		SUM, MUL, APILA
	};

	abstract public ICOD ci();

	abstract public void ejecuta(TinyVM vm);

	public int arg1() {
		throw new UnsupportedOperationException("arg1");
	}

	public static class ISuma extends Instruccion {
		private ISuma() {
		}

		public ICOD ci() {
			return ICOD.SUM;
		}

		public String toString() {
			return "SUMA";
		}

		public void ejecuta(TinyVM vm) {
			TinyVM.PValue op2 = vm.pop();
			TinyVM.PValue op1 = vm.pop();
			vm.push(new TinyVM.IntPValue(op1.asInt() + op2.asInt()));
			vm.incCP();
		}
	}

	public static class IMul extends Instruccion {
		private IMul() {
		}

		public ICOD ci() {
			return ICOD.MUL;
		}

		public String toString() {
			return "MUL";
		}

		public void ejecuta(TinyVM vm) {
			TinyVM.PValue op2 = vm.pop();
			TinyVM.PValue op1 = vm.pop();
			vm.push(new TinyVM.IntPValue(op1.asInt() * op2.asInt()));
			vm.incCP();
		}
	}

	public static class IApila extends Instruccion {
		private IApila(String val) {
			try {
				this.val = Integer.valueOf(val).intValue();
			} catch (NumberFormatException e) {
				this.val = 0;
			}
		}

		public ICOD ci() {
			return ICOD.APILA;
		}

		public int arg1() {
			return val;
		}

		public String toString() {
			return "APILA(" + val + ")";
		}

		public void ejecuta(TinyVM vm) {
			vm.push(new TinyVM.IntPValue(val));
			vm.incCP();
		}

		private int val;
	}

	public static Instruccion nuevaISuma() {
		if (isuma == null) {
			isuma = new ISuma();
		}
		return isuma;
	}

	public static Instruccion nuevaIMul() {
		if (imul == null) {
			imul = new IMul();
		}
		return imul;
	}

	public static Instruccion nuevaIApila(String val) {
		return new IApila(val);
	}

	private static ISuma isuma = null;
	private static IMul imul = null;
}
